use rbatis::rbatis_codegen::ops::AsProxy;
use rocket::{post, get, put, delete};
use rocket::form::FromForm;
use rocket::serde::json::{serde_json::json, Value, Json};
use rocket::serde::{Deserialize};
use rocket::time::macros::time;
use serde::Serialize;
use rbatis::rbdc::datetime::DateTime;
use crate::domain::goods::Goods;

use crate::domain::goods_shop_cart::GoodsShopcart;
use crate::domain::order::Order;
use crate::RB;
use crate::response::response_object::RespData;

// #[serde(crate = "rocket::serde")]
#[derive(FromForm, Deserialize)]
pub struct PostData {
    num: u32,
    good_id: u32,
    user_id: u32,
}

#[post("/wxUser/addToShopCart", data = "<post_data>")]
pub async fn add_to_shop_cart(post_data: Json<PostData>) -> Value {
    let cart = GoodsShopcart {
        id: None,
        user_id: Some(post_data.user_id),
        goods_id: Some(post_data.good_id),
        num: Some(post_data.num),
        status: Some(1),
    };
    let mut rb = RB.clone();
    let res;
    let query_res = GoodsShopcart::selectByGoodIdAndUserId(&mut rb, post_data.good_id, post_data.user_id).await;
    match query_res {
        Ok(query_res) => {
            if query_res.len() == 0 {
                res = GoodsShopcart::insert(&mut rb, &cart).await;
            } else {
                let mut cart: GoodsShopcart = query_res.get(0).unwrap().to_owned();

                cart.num = Option::from(cart.num.unwrap() + 1);
                res = GoodsShopcart::update_by_column(&mut rb, &cart, "id").await;
            }
        }
        Err(_) => {
            return json!(RespData::<()>::error());
        }
    };
    return match res {
        Ok(_) => {
            json!(RespData::<()>::success(()))
        }
        Err(_) => {
            json!(RespData::<()>::error())
        }
    };
}

#[derive(Deserialize, Serialize)]
pub struct Cart {
    pub(crate) good: Goods,
    pub num: u32,
    pub status: u32,
    pub id: u32,
}

#[get("/wxUser/getUserCart/<user_id>")]
pub async fn get_user_cart(user_id: u32) -> Value {
    let mut rb = RB.clone();
    let res = GoodsShopcart::select_by_column(&mut rb, "user_id", user_id).await.unwrap();
    let mut carts: Vec<Cart> = vec![];
    for cart in res {
        if cart.status.unwrap() == 2 { continue; }
        let good = Goods::select_by_column(&mut rb, "id", cart.goods_id).await.unwrap().to_owned();
        let ca = Cart {
            good: good.get(0).unwrap().to_owned(),
            num: cart.num.unwrap(),
            status: cart.status.unwrap(),
            id: cart.id.unwrap(),
        };
        carts.push(ca);
    }
    json!(carts)
}

#[put("/wxUser/changeGoodNum", data = "<post_data>")]
pub async fn change_good_num(post_data: Json<GoodsShopcart>) -> Value {
    let res = GoodsShopcart::update_by_column(&mut RB.clone(), &post_data, "id").await;
    return match res {
        Ok(_) => {
            json!(RespData::<()>::success(()))
        }
        Err(_) => {
            json!(RespData::<()>::error())
        }
    };
}

#[delete("/wxUser/deleteGood/<id>")]
pub async fn delete_good(id: u32) -> Value {
    let res = GoodsShopcart::delete_by_column(&mut RB.clone(), "id", id).await;
    return match res {
        Ok(_) => {
            json!(RespData::<()>::success(()))
        }
        Err(_) => {
            json!(RespData::<()>::error())
        }
    };
}

#[get("/wxUser/createOrder/<user_id>/<imm>/<good_id>")]
pub async fn create_order(user_id: u32, imm: bool, good_id: u32) -> Value {
    let mut rb = RB.clone();
    if !imm {
        let res = GoodsShopcart::update_by_user_id_set_status(user_id).await;
        let mut carts_id:String =String::from("");
        for re in res {
            carts_id.push(re.id.unwrap().to_string().parse().unwrap());
            carts_id.push(",".parse().unwrap());
        }
        carts_id.pop();
        let order = Order{
            id: None,
            user_id: Option::from(user_id),
            carts_id: Option::from(carts_id),
            time: Option::from(DateTime::now()),
        };
        let final_res = Order::insert(&mut rb,&order).await;
        return match  final_res{
            Ok(_)=>{
                json!(RespData::success(final_res.unwrap().last_insert_id))
            }
            Err(_)=>{
                json!(RespData::<()>::error())
            }
        };
    } else {
        let goods_id = good_id.to_string();
        let cart = GoodsShopcart {
            id: None,
            user_id: Some(user_id),
            goods_id: Some(good_id),
            num: Some(1),
            status: Some(2),
        };
        let cart_id = GoodsShopcart::insert(&mut rb, &cart).await.unwrap().last_insert_id.u32().to_string();
        let order = Order {
            id: None,
            user_id: Option::from(user_id),
            carts_id: Option::from(cart_id),
            time: Option::from(DateTime::now()),
        };
        let order_res = Order::insert(&mut rb, &order).await.unwrap();
        json!(RespData::success(order_res.last_insert_id))
    }
}

